package com.max.downloader;

import com.max.file.FileAccessor;
import com.max.file.FileMetadata;
import com.max.thread.DownLoadThread;
import com.max.utils.ConnectionUtils;
import org.apache.http.client.HttpClient;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;

import java.io.IOException;
import java.io.RandomAccessFile;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;

/**
 * Created by Maxwell Yu on 4/20/17.
 */
public class DownloadTask {

    private int TOTAL_THREADS = 8;

    private Semaphore freeThreads = new Semaphore(TOTAL_THREADS);

    private ExecutorService pool = Executors.newFixedThreadPool(TOTAL_THREADS);

    private String fileUrl;

    public void startDownload() {

        FileMetadata fileMetadata = ConnectionUtils.getFileMetadata(fileUrl);


        try {

            fileMetadata = prepareDownloadMeta(fileMetadata);

            HttpClient httpClient = prepareHttpConnectionPool(TOTAL_THREADS);
            fileMetadata.setHttpClient(httpClient);

            pool.submit(new DownLoadThread(fileMetadata, 0, fileMetadata.getFileSize()));

            Thread.sleep(5000);
            while (freeThreads.availablePermits() != TOTAL_THREADS) {
                Thread.sleep(5000);
            }

            fileMetadata.getResultFile().close();
            pool.shutdown();

        } catch (IOException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    private CloseableHttpClient prepareHttpConnectionPool(int TOTAL_THREADS) {
        PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager();
        cm.setDefaultMaxPerRoute(TOTAL_THREADS);
        CloseableHttpClient httpClient = HttpClients.custom()
                .setConnectionManager(cm)
                .build();
        return httpClient;
    }


    private FileMetadata prepareDownloadMeta(FileMetadata fileMetadata) throws IOException {
        RandomAccessFile file = FileAccessor.createFile(fileMetadata);


        fileMetadata.setResultFile(file.getChannel());
        fileMetadata.setTotalThreads(TOTAL_THREADS);
        fileMetadata.setFreeThreads(freeThreads);
        fileMetadata.setPool(pool);
        return fileMetadata;
    }


    public String getFileUrl() {
        return fileUrl;
    }

    public void setFileUrl(String fileUrl) {
        this.fileUrl = fileUrl;
    }
}
